package jinyilw.tools.audio;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.Control;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.FloatControl.Type;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.Mixer;
import java.net.URL;

public class WaveRenderer extends BaseAudioRenderer implements LineListener
{
	private Clip clip;
	private static boolean available;
	private static boolean volumeSupported;
	private static Mixer mixer;
	private static final int UNINITIALIZED = 0;
	private static final int INITIALIZING = 1;
	private static final int INITIALIZED = 2;
	private static int rendererStatus = 0;

	public WaveRenderer()
	{
		if (rendererStatus == 0)
		{
			rendererStatus = 1;
			Thread thread = new Thread(() -> {
				try
				{
					URL sample = WaveRenderer.class.getResource("Sample.wav");
					AudioInputStream ain = AudioSystem.getAudioInputStream(sample);
					AudioFormat format = ain.getFormat();
					DataLine.Info info = new DataLine.Info(Clip.class, ain.getFormat(),
							(int) ain.getFrameLength() * format.getFrameSize());
					Clip clip = (Clip) AudioSystem.getLine(info);
					clip.open(ain);
					WaveRenderer.volumeSupported =
							clip.isControlSupported(Type.VOLUME) || clip.isControlSupported(
									Type.MASTER_GAIN);
					clip.drain();
					clip.close();
					Mixer.Info[] mixers = AudioSystem.getMixerInfo();

					for (Mixer.Info value : mixers)
					{
						if ("Java Sound Audio Engine".equals(value.getName()))
						{
							WaveRenderer.mixer = AudioSystem.getMixer(value);
						}
					}

					WaveRenderer.available = true;
				} catch (Throwable var8)
				{
					System.err.println("WARNING: Wave audio playback is not available!");
					WaveRenderer.available = false;
				}

				WaveRenderer.rendererStatus = 2;
			});
			thread.setDaemon(true);
			thread.start();
		}

	}

	public boolean isAvailable()
	{
		if (rendererStatus != 2)
		{
			int i = 0;

			while (rendererStatus != 2 && i++ < 50)
			{
				try
				{
					Thread.sleep(50L);
				} catch (InterruptedException ignored)
				{
				}
			}

			if (rendererStatus != 2)
			{
				rendererStatus = 2;
				available = false;
			}
		}

		return available;
	}

	protected void playSound(URL audioFile)
	{
		try
		{
			if (this.clip != null)
			{
				this.clip.drain();
				this.clip.close();
			}

			AudioInputStream ain = AudioSystem.getAudioInputStream(this.getAudioFile());
			AudioFormat format = ain.getFormat();
			if (format.getEncoding() == Encoding.ULAW || format.getEncoding() == Encoding.ALAW)
			{
				AudioFormat temp = new AudioFormat(Encoding.PCM_SIGNED, format.getSampleRate(),
						format.getSampleSizeInBits() * 2, format.getChannels(),
						format.getFrameSize() * 2, format.getFrameRate(), true);
				ain = AudioSystem.getAudioInputStream(temp, ain);
				format = temp;
			}

			DataLine.Info info = new DataLine.Info(Clip.class, ain.getFormat(),
					(int) ain.getFrameLength() * format.getFrameSize());
			if (mixer != null)
			{
				this.clip = (Clip) mixer.getLine(info);
			} else
			{
				this.clip = (Clip) AudioSystem.getLine(info);
			}

			this.clip.addLineListener(this);
			this.clip.open(ain);
			this.clip.start();
			if (this.volume != 1.0F)
			{
				this.setSoundVolume(this.volume);
			}
		} catch (Exception var5)
		{
			this.status = 4;
			System.err.println(
					"ERROR: Can not playing " + this.getAudioFile() + " caused by: " + var5);
		}

	}

	protected void replaySound(URL audioFile)
	{
		this.clip.setMicrosecondPosition(0L);
		this.clip.start();
		this.clip.addLineListener(this);
	}

	protected void stopSound()
	{
		this.clip.stop();
		this.clip.setMicrosecondPosition(0L);
		this.clip.removeLineListener(this);
	}

	public void update(LineEvent e)
	{
		if (e.getType() == LineEvent.Type.STOP)
		{
			this.status = 3;
			this.clip.stop();
			this.clip.setMicrosecondPosition(0L);
			this.clip.removeLineListener(this);
		}

	}

	protected void setSoundVolume(float volume)
	{
		if (this.clip != null)
		{
			Control.Type vol1 = Type.VOLUME;
			Control.Type vol2 = Type.MASTER_GAIN;
			FloatControl gainControl;
			if (this.clip.isControlSupported(vol1))
			{
				gainControl = (FloatControl) this.clip.getControl(vol1);
				gainControl.setValue(volume);
			} else if (this.clip.isControlSupported(vol2))
			{
				gainControl = (FloatControl) this.clip.getControl(vol2);
				float dB = (float) (
						Math.log((double) volume == 0.0 ? 1.0E-4 : (double) volume) / Math.log(10.0)
								* 20.0);
				gainControl.setValue(dB);
			}

		}
	}

	public boolean isVolumeSupported()
	{
		return volumeSupported;
	}
}